package com.sicnustray.config;

import ch.qos.logback.classic.spi.CallerData;
import ch.qos.logback.classic.spi.ILoggingEvent;
import ch.qos.logback.core.db.DBAppenderBase;
import org.springframework.context.annotation.Configuration;

import java.lang.reflect.Method;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.sql.Timestamp;

@Configuration
public class LogDBAppender extends DBAppenderBase<ILoggingEvent> {

    protected static final Method GET_GENERATED_KEYS_METHOD;

    protected String insertSQL;

    static final int MESSAGE = 1;

    static final int LEVEL_STRING = 2;

    static final int CREATE_TIME = 3;

    static final int LOGGER_NAME = 4;

    static final StackTraceElement EMPTY_CALLER_DATA = CallerData.naInstance();

    static {

        Method getGeneratedKeysMethod;
        try {

            getGeneratedKeysMethod = PreparedStatement.class.getMethod("getGeneratedKeys", (Class[]) null);
        } catch (Exception ex) {
            getGeneratedKeysMethod = null;
        }
        GET_GENERATED_KEYS_METHOD = getGeneratedKeysMethod;
    }

    @Override
    public void start() {

        insertSQL = buildInsertSQL();
        super.start();
    }

    // 新增sql语句
    private static String buildInsertSQL() {
        return "INSERT INTO `logging`(`message`,`level_string`,`created_time`,`logger_name`)" +
                "VALUES (?,?,?,?)";
    }

    @Override
    protected Method getGeneratedKeysMethod() {
        return GET_GENERATED_KEYS_METHOD;
    }

    @Override
    protected String getInsertSQL() {
        return insertSQL;
    }


    private void bindLoggingEventWithInsertStatement(PreparedStatement stmt, ILoggingEvent event) throws SQLException {

        String message = event.getFormattedMessage();

            stmt.setString(MESSAGE, message);

            stmt.setString(LEVEL_STRING, event.getLevel().toString());

            stmt.setTimestamp(CREATE_TIME, new Timestamp(event.getTimeStamp()));

            stmt.setString(LOGGER_NAME, event.getLoggerName());


    }

    @Override
    protected void subAppend(ILoggingEvent eventObject, Connection connection, PreparedStatement statement) throws Throwable {
        bindLoggingEventWithInsertStatement(statement, eventObject);
        int updateCount = statement.executeUpdate();
        if (updateCount != 1) {
            addWarn("Failed to insert loggingEvent");
        }
    }

    @Override
    protected void secondarySubAppend(ILoggingEvent eventObject, Connection connection, long eventId) throws Throwable {
    }
}